package com.app.common.download

import android.os.Handler
import java.lang.Exception
import kotlin.math.roundToInt

interface Event {
    fun onDownloadBegin(path: String, index: Int)
    fun onDownloadComplete(
        path: String,
        localPath: String,
        index: Int,
        isCancel: Boolean,
        error: Exception?,
        workCount: Int
    )

    fun onDownloading(path: String, index: Int, receiveSize: Long, size: Long, progress: Int)
}

abstract class DownloaderDelegate {

    abstract fun internalAddWork(path: String, fileName: String)

    //abstract fun internalAddWorks(vararg path:String)
    abstract fun internalCancelWork(path: String)

    abstract fun internalCancelAll()


    private val eventList = mutableListOf<Event>()
    private val workList = mutableSetOf<String>()
    private val workCacheList = mutableSetOf<String>()
    var workCount = workList.size

    private var currentWorkPosition = -1

    private var lastProgress = -1
    private var curProgress = 0
    fun addEvent(event: Event) {
        eventList += event
    }

    fun removeEvent(event: Event) {
        eventList -= event
    }

    fun updateWorkCount(): Int {
        return workList.size
    }

    open fun release() {
        workList.clear()
        workCacheList.clear()
        eventList.clear()
    }

    fun addWork(path: String, fileName: String) {
        println("====================add Work:${workList.joinToString()} ,${workList.contains(path)}")
        if (workList.contains(path)) {
            return
        }
        workList.add(path)
        workCacheList.add(path)
        internalAddWork(path, fileName)
    }

    fun cancelWork(path: String) {
        workList.remove(path)
        workCacheList.remove(path)
        internalCancelWork(path)
        workComplete(path, "", true)
    }

    fun cancelAll() {
        workList.forEach {
            workComplete(it, "", true)
        }
        workList.clear()
        workCacheList.clear()
        println("====================add Work:clear")
        internalCancelAll()
    }

    private val handler = Handler()
    fun workBegin(path: String) {
        lastProgress = -1
        handler.post {
            currentWorkPosition = workList.indexOf(path)
            eventList.forEach {
                it.onDownloadBegin(path, currentWorkPosition)
            }
        }
    }

    fun workComplete(
        path: String,
        localPath: String,
        isCancel: Boolean = false,
        error: Exception? = null
    ) {
        workCacheList.remove(path)
        handler.post {
            eventList.forEach {
                it.onDownloadComplete(
                    path,
                    localPath,
                    currentWorkPosition,
                    isCancel,
                    error,
                    workCacheList.size
                )
            }
        }
    }

    fun processing(path: String, receiveSize: Long, size: Long) {
        val p = (receiveSize * 100f / size).roundToInt()
        curProgress = p
        if (curProgress != lastProgress) {
            lastProgress = curProgress
            val pos = currentWorkPosition
            handler.post {
                eventList.forEach {
                    it.onDownloading(path, pos, receiveSize, size, p)
                }
            }
        }
    }
}

class EmptyDelegate : DownloaderDelegate() {
    override fun internalAddWork(path: String, fileName: String) {
    }

    override fun internalCancelWork(path: String) {
    }

    override fun internalCancelAll() {
    }
}